/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "HcsCinderClient.h"
#include "protect_engines/hcs/common/HcsHttpStatus.h"
#include "protect_engines/openstack/api/cinder/model/SnapshotDetails.h"

namespace {
const std::string MODULE_NAME = "HcsCinderClient";
const std::string SNAPSHOT_PTRFIX_NAME = "snapshot-";  // fusionstorage 快照名称前缀
using OpenStackPlugin::SNAPSHOT_STATUS_AVALIABLE;
using Defer = std::shared_ptr<void>;
}

namespace HcsPlugin {
bool HcsCinderClient::CheckParams(ModelBase &model)
{
    if (!model.UserInfoIsSet()) {
        ERRLOG("User info does not set.");
        return false;
    }
    if (!model.IamUserInfoIsSet()) {
        ERRLOG("Iam User info does not set.");
        return false;
    }
    if (!model.DomainIsSet()) {
        ERRLOG("Domain does not set.");
        return false;
    }
    if (!model.EndPointIsSet()) {
        ERRLOG("Endpoint does not set.");
        return false;
    }
    if (!model.ScopeValueIsSet()) {
        ERRLOG("Scope value does not set.");
        return false;
    }
    if (!model.SetRegionIsSet()) {
        ERRLOG("Region does not set.");
        return false;
    }
    return true;
}

void HcsCinderClient::FormRequestInfo(ModelBase &srcRequest, ModelBase &dstRequest)
{
    dstRequest.SetRegion(srcRequest.GetRegion());
    dstRequest.SetScopeValue(srcRequest.GetScopeValue());
    dstRequest.SetEndpoint(srcRequest.GetEndpoint());
    dstRequest.SetUserInfo(srcRequest.GetUserInfo());
    dstRequest.SetIamUserInfo(srcRequest.GetIamUserInfo());
    dstRequest.SetDomain(srcRequest.GetDomain());
    dstRequest.SetToken(srcRequest.GetToken());
}

bool HcsCinderClient::GetTokenEndPoint(ModelBase &request, std::string &tokenStr, std::string &endpoint)
{
    if (!HCSTokenMgr::GetInstance().GetToken(request, tokenStr, endpoint)) {
        ERRLOG("Get token failed.");
        return false;
    }
    return true;
}

std::shared_ptr<GetSnapshotResponse> HcsCinderClient::GetSnapshot(GetSnapshotRequest &request)
{
    std::string endpoint;
    std::string tokenStr;
    Defer _(nullptr, [&](...) { Module::CleanMemoryPwd(tokenStr); });
    if (!GetTokenEndPoint(request, tokenStr, endpoint)) {
        return nullptr;
    }
    RequestInfo reqInfo;
    reqInfo.m_method = "GET";
    reqInfo.m_resourcePath = "{endpoint}/os-hw_snapshots/{snapid}";
    reqInfo.m_pathParams["endpoint"] = std::move(endpoint);
    reqInfo.m_pathParams["snapid"] = request.GetSnapshotId();
    reqInfo.m_queryParams = {};
    reqInfo.m_headerParams["Content-Type"] = "application/json";
    reqInfo.m_headerParams["X-Auth-Token"] = std::move(tokenStr);
    // fusionstorage 以快照名称标识ID snapshot-ID, 调用删除接口时需要用纯ID调用
    if (reqInfo.m_pathParams["snapid"].find(SNAPSHOT_PTRFIX_NAME) != std::string::npos) {
        reqInfo.m_pathParams["snapid"] = reqInfo.m_pathParams["snapid"].substr(SNAPSHOT_PTRFIX_NAME.size());
    }
    reqInfo.m_auth = request.GetUserInfo();
    std::shared_ptr<GetSnapshotResponse> response = std::make_shared<GetSnapshotResponse>();
    if (CallApi(reqInfo, response, request) != VirtPlugin::SUCCESS) {
        ERRLOG("Cinder get snap info failed, errorCode: %d, errorString: %s",
            response->GetErrCode(), response->GetErrString().c_str());
        return nullptr;
    }
    if (!response->Serial()) {
        ERRLOG("Cinder get snap serial failed.");
        return response;
    }
    return response;
}

std::shared_ptr<ShowSnapshotListResponse> HcsCinderClient::ShowSnapshotList(ShowSnapshotListRequest &request)
{
    std::string uri = "{endpoint}/os-hw_snapshots/detail";
    std::string endpoint;
    std::string tokenStr;
    if (!GetTokenEndPoint(request, tokenStr, endpoint)) {
        return nullptr;
    }
    RequestInfo reqInfo;
    reqInfo.m_method = "GET";
    reqInfo.m_resourcePath = uri;
    reqInfo.m_pathParams["endpoint"] = std::move(endpoint);
    reqInfo.m_headerParams["X-Auth-Token"] = std::move(tokenStr);
    if (request.LimitIsSet()) {
        reqInfo.m_queryParams["limit"] = request.GetLimit();
    }
    if (request.OffsetIsSet()) {
        reqInfo.m_queryParams["offset"] = request.GetOffset();
    }
    if (request.VolumeIdIsSet()) {
        reqInfo.m_queryParams["volume_id"] = request.GetVolumeId();
    }
    reqInfo.m_auth = request.GetUserInfo();
    std::shared_ptr<ShowSnapshotListResponse> response = std::make_shared<ShowSnapshotListResponse>();
    if (CallApi(reqInfo, response, request) != SUCCESS) {
        ERRLOG("Call show snapshot list API failed. Error: %s - %s",
            std::to_string(response->GetErrCode()).c_str(), response->GetErrString().c_str());
        return nullptr;
    }

    if (!response->Serial()) {
        ERRLOG("Set snapshot list failed.");
        return nullptr;
    }
    return response;
}
}